#ifndef VECTOR_H
#define VECTOR_H

#include <iostream>
#include <stdexcept>

using namespace std;

template <class T>
class Vector {
public:
  Vector();                      // creates an empty vector
  Vector(int size);              // creates a vector for holding 'size' elements
  Vector(const Vector& r);       // the copy ctor
  ~Vector();                     // destructs the vector 
  T& operator[](int index);      // accesses the specified element without bounds checking
  T& at(int index);              // accesses the specified element, throws an exception of
                                 // type 'std::out_of_range' when index <0 or >=m_nSize
  int size() const;              // return the size of the container
  void push_back(const T& x);    // adds an element to the end 
  void clear();                  // clears the contents
  bool empty() const;            // checks whether the container is empty 
private:
  void inflate();                // expand the storage of the container to a new capacity,
                                 // e.g. 2*m_nCapacity
  T *m_pElements;                // pointer to the dynamically allocated storage
  int m_nSize;                   // the number of elements in the container
  int m_nCapacity;               // the total number of elements that can be held in the
                                 // allocated storage
};

template <class T>
Vector<T>::Vector() :
    m_pElements(nullptr), m_nSize(0), m_nCapacity(0) {
        //creates an empty vector
    }

template <class T>
Vector<T>::Vector(int size) :
    m_pElements(new T[size]), m_nSize(size), m_nCapacity(size) {
        //creates a vector for holding 'size' elements
    }

template <class T>
Vector<T>::Vector(const Vector& r) :
    m_pElements(new T[r.m_nCapacity]), m_nSize(r.m_nSize), m_nCapacity(r.m_nCapacity)
{
    // the copy ctor
    for (int i = 0; i < m_nSize; ++i) {
        m_pElements[i] = r.m_pElements[i];
    }
}

template <class T>
Vector<T>::~Vector() {
    // destructs the vector
    delete[] m_pElements;
}

template <class T>
T& Vector<T>::operator[](int index) {
    // accesses the specified element without bounds checking
    return m_pElements[index];
}

template <class T>
T& Vector<T>::at(int index) {
    // accesses the specified element, throws an exception of
    // type 'std::out_of_range' when index <0 or >=m_nSize
    if (index < 0 || index >= m_nSize) {
        throw out_of_range("Index out of range");
    }
    return m_pElements[index];
}

template <class T>
int Vector<T>::size() const {
    // return the size of the container
    return m_nSize;
}

template <class T>
void Vector<T>::push_back(const T& x) {
    // adds an element to the end 
    if (m_nSize == m_nCapacity) {
        inflate(); //容量不足时，先扩容
    }
    m_pElements[m_nSize++] = x;
}

template <class T>
void Vector<T>::clear() {
    // clears the contents
    delete[] m_pElements;
    m_pElements = nullptr;
    m_nSize = 0;
    m_nCapacity = 0;
}

template <class T>
bool Vector<T>::empty() const {
    // checks whether the container is empty 
    return m_nSize == 0;
}

template <class T>
void Vector<T>::inflate() {
    // expand the storage of the container to a new capacity,e.g. 2*m_nCapacity
    if(m_nCapacity == 0){
        m_nCapacity = 1;//若原来容量为0,则将容量变为1
    }
    else{
        m_nCapacity *= 2;//若原来容量>0,则将容量扩大为2倍
    } 
    T* newElements = new T[m_nCapacity];
    for (int i = 0; i < m_nSize; ++i) {
        newElements[i] = m_pElements[i];
    }
    delete[] m_pElements;
    m_pElements = newElements;
}

#endif